﻿#region Header

/*
    This file is part of ndoctor-statistics.

    ndoctor-statistics is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ndoctor-statistics is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ndoctor-statistics.  If not, see <http://www.gnu.org/licenses/>.
*/

#endregion Header

namespace Probel.NDoctor.Statistics.RepositoriesImpl
{
    using System.Collections.Generic;
    using System.Linq;

    using MongoDB.Driver;
    using MongoDB.Driver.Linq;

    using Probel.NDoctor.Statistics.Domain;
    using Probel.NDoctor.Statistics.Helpers;

    internal class MongoRepository : IRepository
    {
        #region Fields

        protected readonly MongoDatabase Database;

        private const string TABLE_APP = "applications";
        private const string TABLE_DURATION = "durations";
        private const string TABLE_STATISTICS = "statistics";

        private MongoCollection<Application> applications = null;
        private MongoCollection<SessionDuration> durations = null;
        private MongoCollection<StatisticEntry> statistics = null;

        #endregion Fields

        #region Constructors

        public MongoRepository(MongoDatabase database)
        {
            this.Database = database;

            this.applications = this.Database.GetCollection<Application>(TABLE_APP);
            this.durations = this.Database.GetCollection<SessionDuration>(TABLE_DURATION);
            this.statistics = this.Database.GetCollection<StatisticEntry>(TABLE_STATISTICS);
        }

        #endregion Constructors

        #region Properties

        /// <summary>
        /// Gets the users.
        /// </summary>
        public IEnumerable<Application> Applications
        {
            get
            {
                return this.applications.AsQueryable();
            }
        }

        /// <summary>
        /// Gets the durations.
        /// </summary>
        public IEnumerable<SessionDuration> Durations
        {
            get
            {
                return this.durations.AsQueryable();
            }
        }

        /// <summary>
        /// Gets the statistics.
        /// </summary>
        public IEnumerable<StatisticEntry> Statistics
        {
            get
            {
                return this.statistics.AsQueryable();
            }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Clears the database. It'll wipe all the data.
        /// </summary>
        public void Clear()
        {
            this.applications.Drop();
            this.statistics.Drop();
            this.durations.Drop();
        }

        /// <summary>
        /// Imports the specified applications into the remote database.
        /// </summary>
        /// <param name="applications">The applications.</param>
        /// <param name="statistics">The statistics.</param>
        /// <param name="durations">The durations.</param>
        public void Import(IEnumerable<Application> applications, IEnumerable<StatisticEntry> statistics, IEnumerable<SessionDuration> durations)
        {
            applications.NormaliseToLocal();
            statistics.NormaliseToLocal();
            durations.NormaliseToLocal();

            if (applications.Count() > 0) { this.applications.InsertBatch(applications); }
            if (statistics.Count() > 0) { this.statistics.InsertBatch(statistics); }
            if (durations.Count() > 0) { this.durations.InsertBatch(durations); }
        }

        /// <summary>
        /// Exports the specified statistics into the remote repository.
        /// </summary>
        /// <param name="theseItems">The statistics.</param>
        /// <param name="appKey">The app key.</param>
        public void Insert(IEnumerable<StatisticEntry> theseItems)
        {
            this.statistics.InsertBatch(theseItems);
        }

        /// <summary>
        /// Insert a new user into the database
        /// </summary>
        /// <param name="thisItem">The user.</param>
        public void Insert(Application thisItem)
        {
            this.applications.Insert(thisItem);
        }

        /// <summary>
        /// Exports the specified durations into the remote repository.
        /// </summary>
        /// <param name="durations">The durations.</param>
        public void Insert(IEnumerable<SessionDuration> theseItems)
        {
            this.durations.InsertBatch(theseItems);
        }

        /// <summary>
        /// Exports the specified durations into the remote repository.
        /// </summary>
        /// <param name="duration"></param>
        public void Insert(SessionDuration thisItem)
        {
            this.durations.Insert(thisItem);
        }

        /// <summary>
        /// Inserts the specified statistic into the remote repository.
        /// </summary>
        /// <param name="statistic">The statistic.</param>
        public void Insert(StatisticEntry theseItems)
        {
            this.statistics.Insert(theseItems);
        }

        /// <summary>
        /// Updates the specified application.
        /// </summary>
        /// <param name="application">The application.</param>
        public void Update(Application thisItem)
        {
            this.applications.Save(thisItem);
        }

        #endregion Methods
    }
}